﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using ITU.MDD.UPML;
using Microsoft.VisualStudio.Modeling;

namespace MDD.PML.Utility
{
    internal class T2PSM
    {
        private static Store psmstore = null;
        private static DocumentTypePackage psm = null;
        private static IEnumerable<XElement> documentTypes = null;

        internal static void Transform(string filePath)
        {
            documentTypes = XElement.Load(filePath).Elements("DocumentTypes").Elements("DocumentType");

            if (documentTypes != null)
            {
                psmstore = new Store(typeof(UPMLDomainModel));

                using (Transaction trans = psmstore.TransactionManager.BeginTransaction("Create Umbraco PSM from xml"))
                {
                    psm = new DocumentTypePackage(psmstore);
                    foreach (XElement documentType in documentTypes)
                    {
                        CreateDocumentType(documentType);
                    }

                    try
                    {
                        SerializationResult result = new SerializationResult();

                        Char separator = '_';
                        string fileName = string.Format("{0}.upml", DateTime.Now.ToString()
                            .Replace('/', separator)
                            .Replace(' ', separator)
                            .Replace(':', separator));
                        
                        string path = Path.Combine(Directory.GetCurrentDirectory(), fileName);
                        UPMLSerializationHelper.Instance.SaveModel(result, psm, path);

                        if (result.Failed)
                        {
                            foreach (SerializationMessage message in result)
                            {
                                Console.WriteLine(message);
                            }
                        }
                    }
                    catch (IOException ex)
                    {
                        throw ex;
                    }
                }
            }
        }

        private static void CreateDocumentType(XElement documentType)
        {

            foreach (var info in documentType.Elements("Info"))
            {
                string master = info.Element("Master") == null ? string.Empty : info.Element("Master").Value;
                if (!string.IsNullOrEmpty(master))
                    return;

                string alias = info.Element("Alias").Value;

                DocumentType documenttype = new DocumentType(psmstore)
                {
                    Name = info.Element("Name").Value,
                    Alias = info.Element("Alias").Value,
                    Description = info.Element("Description").Value
                };

                foreach (var genericproperty in documentType.Element("GenericProperties").Elements("GenericProperty"))
                {
                    GenericProperty prop = new GenericProperty(psmstore)
                    {
                        Name = genericproperty.Element("Name").Value,
                        Alias = genericproperty.Element("Alias").Value,
                        Description = genericproperty.Element("Description").Value,
                        Mandatory = genericproperty.Element("Description").Value.ToLower() == "true" ? true : false,
                        PropertyType = MapPropertyType(genericproperty.Element("Type").Value)
                    };

                    psm.GenericProperties.Add(prop);
                }

                psm.DocumentTypes.Add(documenttype);

                if (string.IsNullOrEmpty(master))
                {
                    // Master is an optional element is Umbraco; that it might not be present, be empty or have a value.
                    IEnumerable<XElement> children = documentTypes.Where(x => x.Element("Info").Element("Master") != null 
                        && x.Element("Info").Element("Master").Value == alias);
                    foreach (XElement child in children)
                    {
                        CreateChildPageModel(child, documenttype);
                    }
                }
            }
        }

        private static GenericPropertyType MapPropertyType(string genericPropertyType)
        {
            switch (genericPropertyType)
            {
                case "5e9b75ae-face-41c8-b47e-5f4b0fd82f83":
                    {
                        return GenericPropertyType.RichTextEditor;
                    }
                case "60b7dabf-99cd-41eb-b8e9-4d2e669bbde9":
                    {
                        return GenericPropertyType.SimpleEditor;
                     }
                case "67db8357-ef57-493e-91ac-936d305e0f2a":
                    {
                        return GenericPropertyType.TextboxMultiple;
                    }
                case "ec15c1e5-9d90-422a-aa52-4f7622c63bea":
                    {
                        return GenericPropertyType.TextString;
                    }
                case "a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6":
                    {
                        return GenericPropertyType.DropDown;
                    }
                case "928639ed-9c73-4028-920c-1e55dbb68783":
                    {
                        return GenericPropertyType.DropdownMultiple;
                    }
                case "b4471851-82b6-4c75-afa4-39fa9c6a75e9":
                    {
                        return GenericPropertyType.CheckboxList;
                    }
                case "a52c7c1c-c330-476e-8605-d63d3b84b6a6":
                    {
                        return GenericPropertyType.Radiobox;
                    }
                case "23e93522-3200-44e2-9f29-e61a6fcbb79a":
                    {
                        return GenericPropertyType.DatePicker;
                    }
                case "b6fb1622-afa5-4bbf-a3cc-d9672a442222":
                    {
                        return GenericPropertyType.DatePickerWithTime;
                    }
                case "ead69342-f06d-4253-83ac-28000225583b":
                    {
                        return GenericPropertyType.MediaPicker;
                    }
                case "38b352c1-e9f8-4fd8-9324-9a2eab06d97a":
                    {
                        return GenericPropertyType.Boolean;
                    }
                case "f8d60f68-ec59-4974-b43b-c46eb5677985":
                    {
                        return GenericPropertyType.ApprovedColor;
                    }
                case "158aa029-24ed-4948-939e-c3da209e5fba":
                    {
                        return GenericPropertyType.ContentPicker;
                    }
                case "cccd4ae9-f399-4ed2-8038-2e88d19e810c":
                    {
                        return GenericPropertyType.FolderBrowser;
                    }
                case "7a2d436c-34c2-410f-898f-4a23b3d79f54":
                    {
                        return GenericPropertyType.ImageCropper;
                    }
                case "6c738306-4c17-4d88-b9bd-6546f3771597":
                    {
                        return GenericPropertyType.Label;
                    }
                case "474fcff8-9d2d-11de-abc6-ad7a56d89593":
                    {
                        return GenericPropertyType.MacroContainer;
                    }
                case "39f533e4-0551-4505-a64b-e0425c5ce775":
                    {
                        return GenericPropertyType.MemberPicker;
                    }
                case "71b8ad1a-8dc2-425c-b6b8-faa158075e63":
                    {
                        return GenericPropertyType.RelatedLinks;
                    }
                case "4023e540-92f5-11dd-ad8b-0800200c9a66":
                    {
                        return GenericPropertyType.Tags;
                    }
                case "cdbf0b5d-5cb2-445f-bc12-fcaaec07cf2c":
                    {
                        return GenericPropertyType.UltimatePicker;
                    }
                case "5032a6e6-69e3-491d-bb28-cd31cd11086c":
                    {
                        return GenericPropertyType.Upload;
                    }
                default:
                    throw new Exception("Error mapping generic property in T2M transformation");
            }
        }

        private static void CreateChildPageModel(XElement documentType, DocumentType parentDocumentType)
        {
            foreach (XElement info in documentType.Elements("Info"))
            {
                string master = info.Element("Master").Value;
                string alias = info.Element("Alias").Value;

                DocumentType documenttype = new DocumentType(psmstore)
                {
                    Name = info.Element("Name").Value,
                    Alias = info.Element("Alias").Value,
                    Description = info.Element("Description").Value
                };

                foreach (XElement genericproperty in documentType.Element("GenericProperties").Elements("GenericProperty"))
                {
                    GenericProperty prop = new GenericProperty(psmstore)
                    {
                        Name = genericproperty.Element("Name").Value,
                        Alias = genericproperty.Element("Alias").Value,
                        Description = genericproperty.Element("Description").Value,
                        Mandatory = genericproperty.Element("Description").Value.ToLower() == "true" ? true : false,
                        PropertyType = GenericPropertyType.Boolean
                    };

                    documenttype.GenericProperties.Add(prop);
                    psm.GenericProperties.Add(prop);
                }

                parentDocumentType.Children.Add(documenttype);
                psm.DocumentTypes.Add(documenttype);

                // Master is an optional element is Umbraco; that it might not be present, be empty or have a value.
                IEnumerable<XElement> children = documentTypes.Where(x => x.Element("Info").Element("Master") != null
                    && x.Element("Info").Element("Master").Value == alias);
                foreach (XElement child in children)
                {
                    CreateChildPageModel(child, documenttype);
                }
            }
        }
    }
}